package com.wx.service.impl;

import cn.hutool.core.date.DateUtil;
import com.google.code.kaptcha.Producer;
import com.google.common.collect.Maps;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.wx.client.SysFileClient;
import com.wx.client.SysSmsClient;
import com.wx.common.BaseEntity;
import com.wx.constants.Constants;
import com.wx.constants.RedisKeyPrefix;
import com.wx.domain.dto.NurseDto;
import com.wx.entity.SysAddress;
import com.wx.entity.SysAgreement;
import com.wx.entity.SysNurse;
import com.wx.enums.SmsTemplateEnum;
import com.wx.exception.BusinessException;
import com.wx.mapper.SysNurseMapper;
import com.wx.service.*;
import com.wx.utils.SnowFlakeUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * <p>Title:      SysPatientServiceImpl. </p>
 * <p>Description  </p>
 * <p>Copyright: Copyright (c) 2016</p>
 * <p>Company:    医百科技有限公司 </p>
 *
 * @author         yangwensheng@100doc.com.cn
 * @since      2021-03-03 11:36:07
 */
@Service
public class SysNurseServiceImpl extends BaseServiceImpl<SysNurse> implements SysNurseService {

    @Resource
    private SysNurseMapper sysNurseMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private Producer defaultKaptcha;

    @Resource
    private SysSmsClient sysSmsClient;

    @Resource
    private SysFileClient sysFileClient;

    @Resource
    private SysAgreementService sysAgreementService;

    @Resource
    private SysGeneratorCodeService sysGeneratorCodeService;

    @Resource
    private SysAddressService sysAddressService;


    @Override
    public List<SysNurse> listPage(SysNurse sysNurse){
        List<SysNurse> sysNurses = sysNurseMapper.listPage(sysNurse);
        if(!CollectionUtils.isEmpty(sysNurses)){
            List<SysAddress> sysAddresses = sysAddressService.getAll();
            Map<String, String> addRessMap = sysAddresses.stream().collect(Collectors.toMap(SysAddress::getCode, SysAddress::getName));

            List<String> nurseIds = sysNurses.stream().map(BaseEntity::getId).collect(Collectors.toList());
            List<SysAgreement> sysAgreementList = sysAgreementService.batchQueryByPatientIds(nurseIds, Constants.TWO);
            Map<String, String> agreementMap = sysAgreementList.stream().collect(Collectors.toMap(SysAgreement::getUserId, SysAgreement::getSignCode));
            for (SysNurse sysNurs : sysNurses) {
                sysNurs.setProvinceName(addRessMap.get(sysNurs.getProvinceCode()));
                sysNurs.setCityName(addRessMap.get(sysNurs.getCityCode()));
                sysNurs.setAreaName(addRessMap.get(sysNurs.getAreaCode()));
                sysNurs.setAgreementCode(agreementMap.get(sysNurs.getId()));
            }
        }
        return sysNurses;
    }

    @Override
    public int saveNurse(SysNurse sysNurse) {
        sysNurse.setId(SnowFlakeUtil.getStringId());
        SysNurse query = new SysNurse();
        query.setIdNum(sysNurse.getIdNum());
        SysNurse nurse = sysNurseMapper.selectOne(query);
        if(nurse != null){
            throw new BusinessException("该身份证号对应的护士信息已经录入到系统中");
        }
        SysNurse query1 = new SysNurse();
        query1.setPhone(sysNurse.getPhone());
        SysNurse nurse1 = sysNurseMapper.selectOne(query);
        if(nurse1 != null){
            throw new BusinessException("该手机号对应的护士信息已经录入到系统中，请更换其它手机号");
        }
        return sysNurseMapper.insertSelective(sysNurse);
    }

    @Override
    public int updateStatus(String id, Integer status, String userId, String realName) {
        SysNurse nurse = sysNurseMapper.selectByPrimaryKey(id);
        if(nurse == null){
            throw new BusinessException("查询护士信息不存在");
        }
        if(StringUtils.isEmpty(nurse.getOpenId())){
            throw new BusinessException("该护士还未进行实名认证，不能进行审批");
        }
        SysNurse update = new SysNurse();
        update.setId(nurse.getId());
        update.setAuditStatus(status);
        update.setUpdateDate(new Date());
        update.setUpdateBy(userId);
        update.setUpdater(realName);
        return sysNurseMapper.updateByPrimaryKeySelective(update);
    }

    @Override
    public SysNurse selectById(String contactsId) {
        return sysNurseMapper.selectById(contactsId);
    }

    @Override
    public int updateStatus(SysNurse sysNurse) {
        if(StringUtils.isEmpty(sysNurse.getId())){
            throw new BusinessException("护士id不能为空");
        }
        if(StringUtils.isEmpty(sysNurse.getIdCardFront())){
            throw new BusinessException("身份证正面的url地址不能为空");
        }
        if(StringUtils.isEmpty(sysNurse.getIdCardBack())){
            throw new BusinessException("身份证反面的url地址不能为空");
        }
        if(StringUtils.isEmpty(sysNurse.getIdNum())){
            throw new BusinessException("身份证号不能为空");
        }
        if(StringUtils.isEmpty(sysNurse.getRealName())){
            throw new BusinessException("姓名不能为空");
        }
        if(sysNurse.getSex() == null){
            throw new BusinessException("性别不能为空");
        }
        SysNurse nurse = sysNurseMapper.selectByPrimaryKey(sysNurse.getId());
        if(nurse == null){
            throw new BusinessException("查询护士信息不存在");
        }
        if(!nurse.getIdNum().equals(sysNurse.getIdNum())){
            throw new BusinessException("解析后的身份证与录入的身份证号不相同，请重新上传进行实名认证");
        }
        if(!nurse.getRealName().equals(sysNurse.getRealName())){
            throw new BusinessException("解析后的身份证与录入的姓名不相同，请重新上传进行实名认证");
        }
        if(!nurse.getSex().equals(sysNurse.getSex())){
            throw new BusinessException("解析后的身份证与录入的性别不相同，请重新上传进行实名认证");
        }
        sysNurse.setId(nurse.getId());
        sysNurse.setUpdateDate(new Date());
        return sysNurseMapper.updateByPrimaryKeySelective(sysNurse);
    }

    @Override
    public List<SysNurse> selectByIds(List<String> nurseIds) {
        return sysNurseMapper.selectByIds(nurseIds);
    }

    @Override
    @Transactional
    public int updateAgreement(String id, String openid, String nickName) throws Exception {
        SysNurse patient = sysNurseMapper.selectByPrimaryKey(id);
        if(patient == null){
            throw new BusinessException("查询护士信息不存在");
        }
        SysNurse update = new SysNurse();
        update.setId(patient.getId());
        update.setAgreement(Integer.valueOf(Constants.ENABLE));
        update.setUpdateDate(new Date());


        // 生成pdf文档
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        org.springframework.core.io.Resource[] resources = resolver.getResources("template/nurseTemplate.pdf");
        org.springframework.core.io.Resource resource = resources[0];
        InputStream inputStream = resource.getInputStream();
        PdfReader reader = new PdfReader(IOUtils.toByteArray(inputStream));

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PdfStamper ps = new PdfStamper(reader, bos);

        Map<String,String> params = Maps.newHashMap();
        params.put("nurseName",patient.getRealName());
        params.put("signDate", DateUtil.format(new Date(),"yyyy年MM月dd日"));

        AcroFields s = ps.getAcroFields();
        //将查询结果封装到Map中再导出
        for (String key : s.getFields().keySet()) {
            s.setField(key, params.get(key));
        }
        ps.setFormFlattening(true);
        ps.close();


//        String saveFilePath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
        String fileName = SnowFlakeUtil.getStringId() + ".pdf";
        File pdfFile = new File(fileName);
        FileOutputStream fos = new FileOutputStream(fileName);
        fos.write(bos.toByteArray());
        fos.close();
        bos.close();

        // 保存文件到对象存储中
        String url = sysFileClient.uploadToTencent(pdfFile, fileName);
        logger.info("===>护士nurseName = {},协议上传后的地址为 url = {}", update.getRealName(), url);


        // 先删除历史协议
        SysAgreement deleteAgreement = new SysAgreement();
        deleteAgreement.setUserType(Constants.TWO);
        deleteAgreement.setUserId(update.getId());
        deleteAgreement.setUpdateBy(openid);
        deleteAgreement.setUpdater(nickName);
        sysAgreementService.updateByUserId(deleteAgreement);

        // 保存协议内容
        SysAgreement sysAgreement = new SysAgreement();
        sysAgreement.setId(SnowFlakeUtil.getStringId());
        sysAgreement.setUserType(Constants.TWO);
        sysAgreement.setUserId(update.getId());
        sysAgreement.setSignTime(new Date());
        sysAgreement.setFileUrl(url);
        sysAgreement.setCreateBy(openid);
        sysAgreement.setCreator(nickName);
        sysAgreement.setUpdateBy(openid);
        sysAgreement.setUpdater(nickName);
        String uuid = sysGeneratorCodeService.fetchUUID(RedisKeyPrefix.nurse_AGREEMENT_KEY, 6, false);
        sysAgreement.setSignCode("AG" + uuid);
        sysAgreementService.save(sysAgreement);

        // 删除临时文件
        File file = new File(pdfFile.getPath());
        if (!file.isDirectory()) {
            file.delete();
        }
        return sysNurseMapper.updateByPrimaryKeySelective(update);
    }

    @Override
    public SysNurse selectByOpenId(String openId) {
        SysNurse sysNurse = sysNurseMapper.selectByOpenId(openId);
        if(sysNurse != null){
            if(Constants.NO.equals(sysNurse.getAuditStatus())){
                throw new BusinessException("您的信息还未审核通过，请联系管理员进行审核");
            }
            if(Constants.TWO.equals(sysNurse.getAuditStatus()) || Constants.THREE.equals(sysNurse.getAuditStatus()) ){
                throw new BusinessException("您的认证信息被管理员审核不同过或者禁用了，请联系管理员");
            }
            List<SysAddress> sysAddresses = sysAddressService.getAll();
            Map<String, String> addRessMap = sysAddresses.stream().collect(Collectors.toMap(SysAddress::getCode, SysAddress::getName));
            sysNurse.setProvinceName(addRessMap.get(sysNurse.getProvinceCode()));
            sysNurse.setCityName(addRessMap.get(sysNurse.getCityCode()));
            sysNurse.setAreaName(addRessMap.get(sysNurse.getAreaCode()));

        }
        return sysNurse;
    }


    @Override
    public int nurseAuthentication(NurseDto nurseDto) {
        SysNurse query = new SysNurse();
        query.setIdNum(nurseDto.getIdNum());
        SysNurse sysNurse = sysNurseMapper.selectOne(query);
        if(sysNurse != null && !nurseDto.getPhone().equals(sysNurse.getPhone())){
            throw new BusinessException("该身份证号对应的患者信息已经存在");
        }
        SysNurse nurse = sysNurseMapper.selectByPrimaryKey(nurseDto.getId());
        if(nurse == null){
            throw new BusinessException("根据id查询护士信息不存在");
        }
        nurse.setAgreement(Integer.valueOf(Constants.ENABLE));
        nurse.setOpenId(nurseDto.getOpenId());
        nurse.setUpdateDate(new Date());
        nurse.setIdNum(nurseDto.getIdNum());
        nurse.setCertificatesType(nurseDto.getCertificatesType());
        nurse.setRealName(nurseDto.getRealName());
        nurse.setSex(nurseDto.getSex());
        return sysNurseMapper.updateByPrimaryKeySelective(nurse);
    }

    @Override
    public SysNurse checkValidateCode(String openId, String mobile, String validateCode) {
        // 验证短信验证码是否正确
        String key = RedisKeyPrefix.SMS_PREFIX + mobile;
        Object obj = redisService.get(key);
        if(Objects.isNull(obj)){
            throw new BusinessException("短信验证码已经过期，请重新获取");
        }
        if(!validateCode.equals(obj.toString())){
            throw new BusinessException("短信验证码不正确");
        }
        SysNurse query = new SysNurse();
        query.setPhone(mobile);
        SysNurse sysNurse = sysNurseMapper.selectOne(query);
        if(sysNurse != null){
            List<SysAddress> sysAddresses = sysAddressService.getAll();
            Map<String, String> addRessMap = sysAddresses.stream().collect(Collectors.toMap(SysAddress::getCode, SysAddress::getName));
            sysNurse.setProvinceName(addRessMap.get(sysNurse.getProvinceCode()));
            sysNurse.setCityName(addRessMap.get(sysNurse.getCityCode()));
            sysNurse.setAreaName(addRessMap.get(sysNurse.getAreaCode()));
        }
        return sysNurse;
    }

    @Override
    public String generateSmsCode(String mobile) {
        // 根据手机号查询护士信息是否存在
        SysNurse query = new SysNurse();
        query.setPhone(mobile);
        query.setDelFlag(Constants.DELETE_NO);
        SysNurse sysNurse = sysNurseMapper.selectOne(query);
        if(sysNurse == null){
            throw new BusinessException("请联系平台管理员在后台添加您的个人信息，添加后方可进行认证");
        }

        boolean exists = redisService.exists(RedisKeyPrefix.SMS_PREFIX + mobile);
        if (exists) {
            throw new BusinessException("获取短信验证码太频繁，请稍后重试");
        }
        // 生成验证码字符串并保存到redis中
        String createText = defaultKaptcha.createText();
        redisService.set(RedisKeyPrefix.SMS_PREFIX + mobile, createText, RedisKeyPrefix.EXPIRE_TIME_MINUTE);
        // 调用短信服务发送短信验证码
        sysSmsClient.sendSms(new String[]{"+86"+mobile}, SmsTemplateEnum.TEMPLATE_1.getKey(), new String[]{createText,"1"});
        return createText;
    }
}
